from django.views.generic.base import View
from django.shortcuts import render
from django.db.models import Q
from django.http import JsonResponse
from django.conf import settings
from pure_pagination import Paginator, PageNotAnInteger
from utils.mixin_utils import LoginRequiredMixin
from utils.form_utils import get_form_errors
from systems.models import Menu, MenuButton
from systems.forms import MenuForm
from systems.views.dept import get_dept_tree2
from systems.views.dictionary import get_dictionary_tree


class ListView(LoginRequiredMixin, View):
    def get(self, request):
        v_search = request.GET.get('search')
        if v_search:
            v_search = v_search.strip()
            v_objs = Menu.objects.filter(Q(name__icontains=v_search) | Q(web_path__icontains=v_search),
                                         is_delete=0).order_by('parent_id', 'sort')
        else:
            v_objs = Menu.objects.filter(is_delete=0).order_by('parent_id', 'sort')

        # 分页功能实现
        try:
            page = request.GET.get('page', 1)
        except PageNotAnInteger:
            page = 1
        p = Paginator(v_objs, per_page=settings.PAGE_NUM, request=request)
        p_objs = p.page(page)
        p_start = (int(page) - 1) * settings.PAGE_NUM  # 避免分页后每行数据序号从1开始
        return render(request, 'systems/menu_list.html', {'p_objs': p_objs, 'p_start': p_start, 'p_sum': v_objs.count,
                                                          'h_search': v_search})


class AddView(LoginRequiredMixin, View):
    def get(self, request):
        return render(request, 'systems/menu.html', {'h_menus': get_menu_tree(),
                                                     'h_buttons': get_dictionary_tree(),
                                                     'h_dept_belongs': get_dept_tree2()})

    def post(self, request):
        v_form = MenuForm(request.POST)
        if v_form.is_valid():
            new_obj = v_form.save(commit=False)
            new_obj.creator = request.user.username
            new_obj.modifier = request.user.username
            # 数据归属部门不填，则默认为当前创建用户的部门ID
            if new_obj.dept_belong_id is None:
                new_obj.dept_belong_id = request.user.dept_id
            new_obj.save()

            buttons = request.POST.getlist('buttons')
            if len(buttons) > 0:
                for button in buttons:
                    btn_name, btn_key = button.split('|')
                    new_menu_btn = MenuButton(menu=new_obj, name=btn_name, key=btn_key)
                    new_menu_btn.creator = request.user.username
                    new_menu_btn.modifier = request.user.username
                    new_menu_btn.save()
            return JsonResponse({'code': '200', 'msg': '新增成功'})
        else:
            return JsonResponse({'code': '444', 'msg': get_form_errors(v_form)})


class DetailView(LoginRequiredMixin, View):
    def get(self, request):
        v_obj = Menu.objects.get(id=request.GET.get('id'))
        return render(request, 'systems/menu.html', {'h_obj': v_obj,
                                                     'h_menus': get_menu_tree(v_obj.parent),
                                                     'h_buttons': get_dictionary_tree(v_obj.menuPermission.all()),
                                                     'h_dept_belongs': get_dept_tree2(v_obj.dept_belong_id)})


class ModifyView(LoginRequiredMixin, View):
    def post(self, request):
        v_obj = Menu.objects.get(id=request.POST.get('id'))
        v_form = MenuForm(request.POST, instance=v_obj)
        if v_form.is_valid():
            old_obj = v_form.save(commit=False)
            old_obj.modifier = request.user.username
            # 数据归属部门不填，则默认为当前创建用户的部门ID
            if old_obj.dept_belong_id is None:
                old_obj.dept_belong_id = request.user.dept_id
            old_obj.save()

            buttons = request.POST.getlist('buttons')
            if len(buttons) > 0:
                old_menu_buttons = MenuButton.objects.filter(menu=old_obj)
                for old_menu_button in old_menu_buttons:
                    is_exist = False
                    for button in buttons:
                        btn_name, btn_key = button.split('|')
                        if btn_key == old_menu_button.key:
                            is_exist = True
                            break
                    if not is_exist:
                        MenuButton.objects.get(menu=old_obj, key=old_menu_button.key).delete()
                for button in buttons:
                    btn_name, btn_key = button.split('|')
                    is_exist = False
                    for old_menu_button in old_menu_buttons:
                        if old_menu_button.key == btn_key:
                            is_exist = True
                            break
                    if not is_exist:
                        new_menu_btn = MenuButton(menu=old_obj, name=btn_name, key=btn_key)
                        new_menu_btn.creator = request.user.username
                        new_menu_btn.modifier = request.user.username
                        new_menu_btn.save()

            return JsonResponse({'code': '200', 'msg': '修改成功'})
        else:
            return JsonResponse({'code': '444', 'msg': get_form_errors(v_form)})


class DeleteView(LoginRequiredMixin, View):
    def get(self, request, i_id):
        v_user = Menu.objects.get(id=i_id)
        v_user.delete()
        return JsonResponse({'code': '200', 'msg': '删除成功'})


class IconsView(LoginRequiredMixin, View):
    def get(self, request):
        return render(request, 'systems/mdi_icons.html')


def get_user_menu(request):
    """
    获取菜单树，用于左侧菜单栏显示
    YPN 2021-09-19 Create
    :return: 返回树形的菜单结构HTML
    """
    menus = None
    if request.user.is_authenticated:
        if request.user.is_superuser == 1:
            menus = Menu.objects.filter(is_delete=0, visible=1, status=1)
        else:
            menus = Menu.objects.filter(is_delete=0, visible=1, status=1, role__userprofile=request.user).distinct()
    if menus is None:
        return None

    user_menu = ""

    def get_child(i_menu):
        """递归获取树的子节点"""
        exist_child = False
        child_menu = ''
        child_active = False
        for menu1 in menus:
            if menu1.parent is not None and menu1.parent == i_menu:
                exist_child = True
                if menu1.web_path == request.path:
                    child_active = True
                child_menu += get_child(menu1)

        if exist_child:
            parent_menu = '<li class="nav-item nav-item-has-subnav'
            if child_active:
                parent_menu += ' active open'
            parent_menu += '">'
            if i_menu.parent is None:
                # 只有一级菜单拥有图标
                parent_menu += f'<a href="javascript:void(0)"><i class="mdi {i_menu.icon}"></i>{i_menu.name}</a>'
            else:
                parent_menu += f'<a href="javascript:void(0)">{i_menu.name}</a>'
            parent_menu += '<ul class="nav nav-subnav">'
            parent_menu += child_menu
            parent_menu += '</ul>'
            parent_menu += '</li>'
            return parent_menu
        else:
            child_menu = '<li'
            if i_menu.web_path == request.path:
                child_menu += ' class="active"'
            # 是外链时，在新页签打开
            if i_menu.is_link == 1:
                child_menu += f'> <a href="{i_menu.web_path}" target="_blank">{i_menu.name}</a> </li>'
            else:
                child_menu += f'> <a href="{i_menu.web_path}">{i_menu.name}</a> </li>'
            return child_menu

    # 循环一级菜单
    for menu in menus:
        if menu.parent is None:
            user_menu += get_child(menu)
    print(user_menu)

    return user_menu


def get_menu_tree(i_menu=None):
    """
    获取菜单树，可选父节点，用于新增菜单时选择父菜单
    YPN 2021-09-19 Create
    :return: 返回树形的菜单结构
    """
    menu_tree = ''
    menus = Menu.objects.filter(is_delete=0)

    def get_blank(i_num):
        i = 1
        result = ''
        while i <= i_num:
            result += '&nbsp;&nbsp;'
            i = i + 1
        return result

    def get_child(i_menu_id, i_menu_name, i_blank_num, i_selected_menu_id):
        """递归获取树的子节点"""
        exist_child = False
        child_tree = ''
        for menu1 in menus:
            if menu1.parent is not None and menu1.parent.id == i_menu_id:
                exist_child = True
                child_tree += get_child(menu1.id, menu1.name, i_blank_num + 1, i_selected_menu_id)

        if exist_child:
            if i_menu_id == i_selected_menu_id:
                return f'<option selected value="{i_menu_id}">{get_blank(i_blank_num + 1)}{i_menu_name}</option>{child_tree}'
            else:
                return f'<option value="{i_menu_id}">{get_blank(i_blank_num + 1)}{i_menu_name}</option>{child_tree}'
        else:
            if i_menu_id == i_selected_menu_id:
                return f'<option selected value="{i_menu_id}">{get_blank(i_blank_num + 1)}{i_menu_name}</option>'
            else:
                return f'<option value="{i_menu_id}">{get_blank(i_blank_num + 1)}{i_menu_name}</option>'

    for menu in menus:
        if menu.parent is None:
            if i_menu is None:
                menu_tree += get_child(menu.id, menu.name, -1, 0)
            else:
                menu_tree += get_child(menu.id, menu.name, -1, i_menu.id)

    return menu_tree
